<template>
  <div id="iconSelectView">
<!--    popper-class引用的属性必须为公共的class样式才能生效，不能放在scoped中-->
    <el-popover
      ref="popoverRef"
      placement="bottom-start"
      popper-class="el-popper-icon-select-class"
      :width="315"
      trigger="click"
      @before-enter="showIconSelect"
      @before-leave="hideIconSelect"
      @after-leave="searchIcon = '';"
    >
      <template #reference>
<!--        :suffix-icon="selectOption!=''?'CircleClose':iconSelectVisible?'ArrowDown':'ArrowUp'"-->
        <el-input
          placeholder="请选择图标"
          readonly
          v-model="selectOption"
        >
          <template #suffix>
            <el-icon v-if="selectOption!==null&&selectOption!==''" @click="clearValue" class="el-input__icon" style="cursor: pointer;"><CircleClose/></el-icon>
            <el-icon v-else class="el-input__icon">
              <ArrowDown v-if="iconSelectVisible"/>
              <ArrowUp v-else/>
            </el-icon>
          </template>
        </el-input>
      </template>
      <div id="option-body">
        <el-tabs v-model="activeTabName">
          <el-tab-pane name="baseIcon">
            <template #label>
              基本图标
            </template>
            <el-row :gutter="5" justify="start" align="middle" style="width:300px;height: 100%;">
              <el-col :span="4" v-for="(icon) in iconListResult" :key="icon" class="grid-col">
                <el-tooltip :content="icon.name" placement="bottom" effect="light" :offset="0" :hide-after="0" :show-after="500">
                  <el-card shadow="hover" @mouseover="changeIconSize(icon,iconSizeOfBig)" @mouseout="changeIconSize(icon,iconSizeOfNormal)" @click="selectIcon(icon.name)">
                    <el-icon :size="icon.iconSize"><component class="icon" :is="icon.name" /></el-icon>
                  </el-card>
                </el-tooltip>
              </el-col>
            </el-row>
          </el-tab-pane>
        </el-tabs>
        <div id="search-input">
          <el-input
            clearable
            v-model="searchIcon"
            placeholder="搜索图标"
            suffix-icon="Search"
          />
        </div>
      </div>
    </el-popover>
  </div>
</template>

<script lang="ts" setup>
// 图标选择列表
import {
  ref,
  defineComponent,
  onMounted,
  watch,
  computed,
  WritableComputedRef,
  withDefaults,
  defineProps,
  getCurrentInstance,
  unref,
} from 'vue';
import { ElPopover, ElTable } from 'element-plus';
import * as Icons from '@element-plus/icons-vue';

interface Props {
  modelValue: any, // 获取从父组件input类型绑定的值,vue3中使用了modelValue来替代value，并且传递过来的是非ref或reactive类型的值,input方法了改成update:modelValue
  clickAndCloseDialog?:boolean, // 是否点击图标后就关闭对话框
}
const props = withDefaults(defineProps<Props>(), {
  modelValue: () => '',
  clickAndCloseDialog: true,
});
const { proxy } = getCurrentInstance(); // 使用proxy代替ctx，因为ctx只在开发环境有效
// 定义弹出框的ref对象，定义目的用于手动控制关闭
const popoverRef = ref<InstanceType<typeof ElPopover>>();
const iconSelectVisible = ref<boolean>(); // 是否显示下拉框下拉箭头的变量
// const selectOption = ref<string>(''); // 文本框的值
const searchIcon = ref<string>(''); // 搜索框的值
const iconSizeOfBig = 32; // 大图标的尺寸
const iconSizeOfNormal = 20; // 图标的正常尺寸
// tab名称
const activeTabName = ref('baseIcon');
// 与父组件v-model绑定的值进行关联
const selectOption = computed({ // 要转化为ref对象
  get() { // 当父组件的值改变时触发
    return props.modelValue;
  },
  set(val) { // 当本组件的值改变时触发
    // 将本组件的值传给父组件
    proxy.$emit('update:modelValue', val);
  },
});
// 定义图标类
class Icon {
  name: string;

  iconSize: number;

  constructor(name: string, size: number) {
    this.name = name;
    this.iconSize = size;
  }
}
// 定义图标列表
const iconList = ref<Icon[]>([]);
// 组件初始化时获取图标对象，后期待优化
onMounted(() => {
  // 获取element plus的图标名称
  Object.keys(Icons).forEach((key) => {
    iconList.value.push(new Icon(key, iconSizeOfNormal));
  });
});
// 当鼠标经过图标，图标大小的变化
const changeIconSize = (icon:Icon, size:number) => { // 第一个参数：图像对象；第二个参数：要改变的图标大小
  // eslint-disable-next-line no-param-reassign
  icon.iconSize = size;
};
// 模拟下拉框选择
const showIconSelect = () => { // 显示下拉框
  iconSelectVisible.value = true;
};
const hideIconSelect = () => { // 隐藏下拉框
  iconSelectVisible.value = false;
  // 清空搜索框的值
};
// 当点击下拉框中的图标时，为文本框赋值图标的名称
const selectIcon = (name:string) => {
  selectOption.value = name;
  if (props.clickAndCloseDialog) {
    // 点击就关闭弹框。注意，这个hide方法在el-popover组件中没有提示，但是可以关闭弹框
    popoverRef.value!.hide();
    // eslint-disable-next-line no-unused-expressions
    // unref(popoverRef).popperRef?.doClose?.();
  }
};
// 清空文本框的值
const clearValue = () => {
  selectOption.value = '';
  // 后续加上阻止下拉框状态改变代码，让体验更合适
};

// 处理搜索框业务
// 根据搜索框的值显示下拉列表
const iconListResult = computed(() => {
  const array = ref<Icon[]>([]);
  if (searchIcon.value !== '') { // 如果搜索框的值不为空
    iconList.value.forEach((icon:Icon) => { // 遍历已有的集合
      if (icon.name.includes(searchIcon.value)) {
        array.value.push(icon);
      }
    });
  } else { // 如果搜索框的值为空
    array.value = iconList.value;
  }
  return array.value;
});

</script>

<style lang="scss" scoped>
#iconSelectView{
}
#option-body{ /*下拉框主体部分*/
  position: relative;
  #search-input{ /*搜索文本框*/
    position: absolute;
    width:120px;
    right:10px;
    top:1px;
  }
  .grid-col{
    height:50px;
    padding:2px;
    /*设置水平垂直居中*/
    display:flex;
    justify-content: center;
    align-items: center;
    /*设置边框*/
    //border: 1px solid #ededed;
    color: #606266;
    /*text-align:center;*/
    font-size:12px;
    ::v-deep .el-card{
      width:100%;
      height:100%;
      /*设置水平垂直居中，这样el-card__body才能居中*/
      display:flex;
      justify-content: center;
      align-items: center;
      .el-card__body{
        /*设置水平垂直居中,这样里面的图标才能居中*/
        display:flex;
        justify-content: center;
        align-items: center;
      }
    }
  }
}
</style>
